﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ServiceHandler.cs" company="Anton Frattaroli">
//   Copyright (c) Anton Frattaroli. All rights reserved.
// </copyright>
// <summary>
//   Defines the ServiceHandler class.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Lidocaine
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.SqlClient;
    using System.Globalization;
    using System.IO;
    using System.Resources;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Threading;
    using System.Web;
    using AdamTibi.Web.Security;
    using Ionic.Zip;
    using Lidocaine.Properties;

    /// <summary>
    /// The ServiceHandler class.
    /// </summary>
    public class ServiceHandler : IHttpHandler
    {
        #region Properties
        /// <summary>
        /// Gets a value indicating whether or not the IHttpHandler implementation is reusable.
        /// </summary>
        public bool IsReusable
        {
            get { return false; }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Processes HTTP requests.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        public void ProcessRequest(HttpContext context)
        {
            ////Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
            context.Response.ContentType = "text/plain";
            Dictionary<string, Action<HttpContext>> dic = this.GetHandlers();
            if (dic.ContainsKey(context.Request.QueryString["f"]))
            {
                dic[context.Request.QueryString["f"]].Invoke(context);
            }
            else
            {
                context.Response.Write(Strings.ServiceNotFound);
            }
        }

        /// <summary>
        /// Converts DataTable objects to JSON strings.
        /// </summary>
        /// <param name="dt">The DataTable object.</param>
        /// <returns>The JSON string.</returns>
        private static string GetJSONString(DataTable dt)
        {
            string[] strDc = new string[dt.Columns.Count];
            string headStr = string.Empty;
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                strDc[i] = dt.Columns[i].Caption;
                headStr += "\"" + strDc[i] + "\" : \"" + strDc[i] + i.ToString(CultureInfo.InvariantCulture) + "¾" + "\",";
            }

            headStr = headStr.Substring(0, headStr.Length - 1);
            StringBuilder sb = new StringBuilder();
            sb.Append("[");
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                string tempStr = headStr;
                sb.Append("{");
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    tempStr = tempStr.Replace(dt.Columns[j] + j.ToString(CultureInfo.InvariantCulture) + "¾", EscapeJSON(dt.Rows[i][j].ToString()));
                }

                sb.Append(tempStr + "},");
            }

            sb = new StringBuilder(sb.ToString().Substring(0, sb.ToString().Length - 1));
            sb.Append("]");
            if (sb.ToString() == "]")
            {
                return "{}";
            }
            else
            {
                return sb.ToString();
            }
        }

        /// <summary>
        /// Cleans up strings for sending as JSON.
        /// </summary>
        /// <param name="value">The string to clean.</param>
        /// <returns>A string ready to be placed as a JSON value.</returns>
        private static string EscapeJSON(string value)
        {
            return value.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n").Replace("\r", string.Empty);
        }

        /// <summary>
        /// Handles the request to delete a hosted file type.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void DeleteFileType(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                int fileTypeId = 0;
                if (int.TryParse(context.Request["filetypeID"], out fileTypeId))
                {
                    FileType f = new FileType(fileTypeId);
                    IList<Asset> files = Asset.GetFilesByFileType(f);
                    if (files.Count == 0)
                    {
                        f.Delete();
                        context.Response.Write(Strings.FileTypeDeleteSuccessful);
                    }
                    else
                    {
                        string dependentFiles = string.Empty;
                        for (int i = 0; i < files.Count; i++)
                        {
                            dependentFiles += "<li>" + files[i].VirtualPath + "</li>";
                        }

                        context.Response.Write(Strings.FileTypeDeleteFailedDependencies + "<ul>" + dependentFiles + "</ul>");
                    }
                }
                else
                {
                    context.Response.Write(Strings.FileTypeDeleteFailedBadId);
                }
            }
            else
            {
                context.Response.Write("File type deletion failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to add a hosted file type.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void AddFileType(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string extension = context.Request["extension"];
                Regex myRegex = new Regex(@"^[\w]+$");
                if (myRegex.IsMatch(extension))
                {
                    FileType f = FileType.GetFileTypeByExtension(extension);
                    if (f == null)
                    {
                        f = new FileType();
                        f.Extension = extension.ToUpperInvariant();
                        f.Mime = context.Request["mime"].ToUpperInvariant();
                        f.SaveAs();
                        context.Response.Write("File type created successfully.");
                    }
                    else
                    {
                        context.Response.Write("File type creation failed: A file type with this extension already exists.");
                    }
                }
                else
                {
                    context.Response.Write("File type creation failed: Please use only alphanumeric characters for the extension.");
                }
            }
            else
            {
                context.Response.Write("File type creation failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to update a hosted file type.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdateFileType(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                int fileTypeId = 0;
                if (int.TryParse(context.Request["filetypeID"], out fileTypeId))
                {
                    FileType f = new FileType(fileTypeId);
                    f.Mime = context.Request["mime"].ToUpperInvariant();
                    f.Save();
                    context.Response.Write("File type updated successfully.");
                }
                else
                {
                    context.Response.Write("File type update failed: File type identifier parameter not valid.");
                }
            }
            else
            {
                context.Response.Write("File type update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to select all hosted file types.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void LoadFileTypes(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                List<string> filetypesJSON = new List<string>();
                IList<FileType> filetypes = FileType.GetFileTypes();
                for (int i = 0; i < filetypes.Count; i++)
                {
                    filetypesJSON.Add(string.Format(CultureInfo.InvariantCulture, "{{\"FileTypeID\" : \"{0}\",\"Extension\" : \"{1}\",\"Mime\" : \"{2}\"}}", filetypes[i].FileTypeId, filetypes[i].Extension, EscapeJSON(filetypes[i].Mime)));
                }

                context.Response.Write("[" + string.Join(", ", filetypesJSON.ToArray()) + "]");
            }
            else
            {
                context.Response.Write("File type retrieval failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to update a page's title.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsTitle(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                if (int.TryParse(context.Request["pageID"], out pageId))
                {
                    PageLayout p = new PageLayout(pageId);
                    p.Title = context.Request["title"];
                    p.Save();
                    context.Response.Write("Page title update successful.");
                }
                else
                {
                    context.Response.Write("Page title update failed: Page identifier parameter not valid.");
                }
            }
            else
            {
                context.Response.Write("Page title update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to update a page's header.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsHeader(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                if (int.TryParse(context.Request["pageID"], out pageId))
                {
                    int headerId = 0;
                    PageLayout p = new PageLayout(pageId);
                    if (!string.IsNullOrEmpty(context.Request["headerID"]) && int.TryParse(context.Request["headerID"], out headerId))
                    {
                        p.Header = new Template(headerId);
                    }
                    else
                    {
                        p.Header = null;
                    }

                    p.Save();
                    context.Response.Write("Page Header Update Saved.");
                }
                else
                {
                    context.Response.Write("Page header update failed: Identifier parameter not valid.");
                }
            }
            else
            {
                context.Response.Write("Page header update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to update a page's footer.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsFooter(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                if (int.TryParse(context.Request["pageID"], out pageId))
                {
                    int footerId = 0;
                    PageLayout p = new PageLayout(pageId);
                    if (!string.IsNullOrEmpty(context.Request["footerID"]) && int.TryParse(context.Request["footerID"], out footerId))
                    {
                        p.Footer = new Template(footerId);
                    }
                    else
                    {
                        p.Footer = null;
                    }

                    p.Save();
                    context.Response.Write("Page Footer Update Saved.");
                }
                else
                {
                    context.Response.Write("Page footer update failed: Identifier parameter not valid.");
                }
            }
            else
            {
                context.Response.Write("Page footer update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to update a page's stylesheet.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsCSS(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                if (int.TryParse(context.Request["pageID"], out pageId))
                {
                    int scriptId = 0;
                    PageLayout p = new PageLayout(pageId);
                    if (!string.IsNullOrEmpty(context.Request["cssID"]) && int.TryParse(context.Request["cssID"], out scriptId))
                    {
                        p.Css = new Script(scriptId);
                    }
                    else
                    {
                        p.Css = null;
                    }

                    p.Save();
                    context.Response.Write("Page Style Sheet Update Saved.");
                }
                else
                {
                    context.Response.Write("Page stylesheet update failed: Identifier parameter not valid.");
                }
            }
            else
            {
                context.Response.Write("Script update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to update a page's javascript.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsJS(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                if (int.TryParse(context.Request["pageID"], out pageId))
                {
                    int scriptId = 0;
                    PageLayout p = new PageLayout(pageId);
                    if (!string.IsNullOrEmpty(context.Request["jsID"]) && int.TryParse(context.Request["jsID"], out scriptId))
                    {
                        p.JS = new Script(scriptId);
                    }
                    else
                    {
                        p.JS = null;
                    }

                    p.Save();
                    context.Response.Write("Page Javascript Update Saved.");
                }
                else
                {
                    context.Response.Write("Page script update failed: Identifier parameter not valid.");
                }
            }
            else
            {
                context.Response.Write("Script update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to update the order of a page's top navigation groups.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsTopNavOrder(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                int oldOrdinal = 0;
                int newOrdinal = 0;
                if (int.TryParse(context.Request["pageID"], out pageId) && int.TryParse(context.Request["oldOrder"], out oldOrdinal) && int.TryParse(context.Request["newOrder"], out newOrdinal))
                {
                    PageLayout p = new PageLayout(pageId);
                    p.ReorderNavigationGroups(oldOrdinal, newOrdinal, NavigationGroupArea.Top);
                    context.Response.Write("Page top navigation update successful.");
                }
                else
                {
                    context.Response.Write("Page top navigation update failed: One or more parameters not valid.");
                }
            }
            else
            {
                context.Response.Write("Top navigation update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to update the order or a page's left navigation groups.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsLeftNavOrder(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                int oldOrdinal = 0;
                int newOrdinal = 0;
                if (int.TryParse(context.Request["pageID"], out pageId) && int.TryParse(context.Request["oldOrder"], out oldOrdinal) && int.TryParse(context.Request["newOrder"], out newOrdinal))
                {
                    PageLayout p = new PageLayout(pageId);
                    p.ReorderNavigationGroups(oldOrdinal, newOrdinal, NavigationGroupArea.Left);
                    context.Response.Write("Left Navigation Group Order Update Saved.");
                }
                else
                {
                    context.Response.Write("Page left navigation update failed: One or more parameters not valid.");
                }
            }
            else
            {
                context.Response.Write("Left navigation update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to remove one of a page's top navigation groups.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsTopNavRemove(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                int ordinal = 0;
                if (int.TryParse(context.Request["pageID"], out pageId) && int.TryParse(context.Request["order"], out ordinal))
                {
                    PageLayout p = new PageLayout(pageId);
                    p.RemoveNavigationGroupAt(ordinal, NavigationGroupArea.Top);
                    context.Response.Write("Top Navigation Group Removal Update Saved.");
                }
                else
                {
                    context.Response.Write("Page top navigation update failed: One or more parameters not valid.");
                }
            }
            else
            {
                context.Response.Write("Top navigation update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to remove one of a page's left navigation groups.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsLeftNavRemove(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                int ordinal = 0;
                if (int.TryParse(context.Request["pageID"], out pageId) && int.TryParse(context.Request["order"], out ordinal))
                {
                    PageLayout p = new PageLayout(pageId);
                    p.RemoveNavigationGroupAt(ordinal, NavigationGroupArea.Left);
                    context.Response.Write("Left Navigation Group Removal Update Saved.");
                }
                else
                {
                    context.Response.Write("Page left navigation update failed: One or more parameters not valid.");
                }
            }
            else
            {
                context.Response.Write("Left navigation update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to append a top navigation group to a page.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsTopNavAdd(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                if (int.TryParse(context.Request["pageID"], out pageId))
                {
                    NavigationGroup n = new NavigationGroup(context.Request["navName"], NavigationGroupArea.Top);
                    PageLayout p = new PageLayout(pageId);
                    p.AppendNavigationGroup(n);
                    context.Response.Write("Top Navigation Group Addition Update Saved.");
                }
                else
                {
                    context.Response.Write("Page top navigation update failed: Identifier parameter not valid.");
                }
            }
            else
            {
                context.Response.Write("Top navigation update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to append a left navigation group to a page.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsLeftNavAdd(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                if (int.TryParse(context.Request["pageID"], out pageId))
                {
                    NavigationGroup n = new NavigationGroup(context.Request["navName"], NavigationGroupArea.Left);
                    PageLayout p = new PageLayout(pageId);
                    p.AppendNavigationGroup(n);
                    context.Response.Write("Left Navigation Group Addition Update Saved.");
                }
                else
                {
                    context.Response.Write("Page left navigation update failed: Identifier parameter not valid.");
                }
            }
            else
            {
                context.Response.Write("Left navigation update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to update the order of a page's right column modules.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsRightOrder(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                int oldOrdinal = 0;
                int newOrdinal = 0;
                if (int.TryParse(context.Request["pageID"], out pageId) && int.TryParse(context.Request["oldOrder"], out oldOrdinal) && int.TryParse(context.Request["newOrder"], out newOrdinal))
                {
                    PageLayout p = new PageLayout(pageId);
                    p.ReorderModules(oldOrdinal, newOrdinal, UserControlArea.Right);
                    context.Response.Write("Right Content Module Order Update Saved.");
                }
                else
                {
                    context.Response.Write("Page right column update failed: One or more parameters not valid.");
                }
            }
            else
            {
                context.Response.Write("Right column update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to update the order of a page's main column modules.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsMainOrder(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                int oldOrdinal = 0;
                int newOrdinal = 0;
                if (int.TryParse(context.Request["pageID"], out pageId) && int.TryParse(context.Request["oldOrder"], out oldOrdinal) && int.TryParse(context.Request["newOrder"], out newOrdinal))
                {
                    PageLayout p = new PageLayout(pageId);
                    p.ReorderModules(oldOrdinal, newOrdinal, UserControlArea.Main);
                    context.Response.Write("Page main column update successful.");
                }
                else
                {
                    context.Response.Write("Page main column update failed: One or more parameters not valid.");
                }
            }
            else
            {
                context.Response.Write("Main column update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to remove one of a page's right column modules.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsRightRemove(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                int ordinal = 0;
                if (int.TryParse(context.Request["pageID"], out pageId) && int.TryParse(context.Request["order"], out ordinal))
                {
                    PageLayout page = new PageLayout(pageId);
                    page.DeleteRightModule(ordinal);
                    context.Response.Write("Right column update successful.");
                }
                else
                {
                    context.Response.Write("Right column update failed: One or more parameters not valid.");
                }
            }
            else
            {
                context.Response.Write("Right column update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to remove one of a page's main column modules.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsMainRemove(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                int pageId = 0;
                int ordinal = 0;
                if (int.TryParse(context.Request["pageID"], out pageId) && int.TryParse(context.Request["order"], out ordinal))
                {
                    PageLayout page = new PageLayout(pageId);
                    page.DeleteMainModule(ordinal);
                    context.Response.Write("Main column update successful.");
                }
                else
                {
                    context.Response.Write("Main column update failed: One or more parameters not valid.");
                }
            }
            else
            {
                context.Response.Write("Main column update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to append a right column module to a page.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsRightAdd(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.InsertPageRightModule", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@PageID", context.Request["pageID"]);
                        cmd.Parameters.AddWithValue("@ModuleID", context.Request["moduleID"]);
                        cmd.Parameters.AddWithValue("@ContentOrder", context.Request["order"]);
                        cmd.ExecuteNonQuery();
                    }
                }

                context.Response.Write("Right Content Module Addition Update Saved.");
            }
            else
            {
                context.Response.Write("Right column update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to append a main column module to a page.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsMainAdd(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.InsertPageMainModule", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@PageID", context.Request["pageID"]);
                        cmd.Parameters.AddWithValue("@ModuleID", context.Request["moduleID"]);
                        cmd.Parameters.AddWithValue("@ContentOrder", context.Request["order"]);
                        cmd.ExecuteNonQuery();
                    }
                }

                context.Response.Write("Main Content Module Addition Update Saved.");
            }
            else
            {
                context.Response.Write("Main column update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to update the content version of a page.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdatePageSettingsContentVersion(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.UpdatePageContentVersion", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@ID", context.Request["pageID"]);
                        cmd.Parameters.AddWithValue("@BlockID", context.Request["blockID"]);
                        cmd.ExecuteNonQuery();
                    }
                }

                context.Response.Write("Content Version Changed.");
            }
            else
            {
                context.Response.Write("Content version update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to select a page's settings.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void EditPageSettings(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                string pagePath = context.Request["pagePath"];
                string output = string.Empty;
                List<string> jsonHeaders = new List<string>();
                List<string> jsonFooters = new List<string>();
                List<string> jsonCSSs = new List<string>();
                List<string> jsonJSs = new List<string>();
                List<string> jsonTopNavs = new List<string>();
                List<string> jsonLeftNavs = new List<string>();
                List<string> jsonRMods = new List<string>();
                List<string> jsonMMods = new List<string>();
                List<string> jsonVersions = new List<string>();
                List<string> jsonPTopNavs = new List<string>();
                List<string> jsonPLeftNavs = new List<string>();
                List<string> jsonPRMods = new List<string>();
                List<string> jsonPMMods = new List<string>();
                PageLayout p = new PageLayout(pagePath);
                output += string.Format(CultureInfo.InvariantCulture, "\"pID\" : \"{0}\", \"pTitle\" : \"{1}\", \"pHead\" : \"{2}\", \"pFoot\" : \"{3}\", \"pCss\" : \"{4}\", \"pJs\" : \"{5}\", \"pCurrentVersion\" : \"{6}\"", p.PageId, p.Title != null ? p.Title : string.Empty, p.Header != null ? p.Header.TemplateId : 0, p.Footer != null ? p.Footer.TemplateId : 0, p.Css != null ? p.Css.ScriptId : 0, p.JS != null ? p.JS.ScriptId : 0, p.Content != null ? p.Content.ContentId : 0);
                Dictionary<int, string> layoutElements = Template.GetTemplates(TemplateArea.Header);
                foreach (KeyValuePair<int, string> kvp in layoutElements)
                {
                    jsonHeaders.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\" : \"{0}\",\"Name\" : \"{1}\"}}", kvp.Key, kvp.Value));
                }

                layoutElements = Template.GetTemplates(TemplateArea.Footer);
                foreach (KeyValuePair<int, string> kvp in layoutElements)
                {
                    jsonFooters.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\" : \"{0}\",\"Name\" : \"{1}\"}}", kvp.Key, kvp.Value));
                }

                layoutElements = Script.GetScripts(ScriptType.Css);
                foreach (KeyValuePair<int, string> kvp in layoutElements)
                {
                    jsonCSSs.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\" : \"{0}\",\"Name\" : \"{1}\"}}", kvp.Key, kvp.Value));
                }

                layoutElements = Script.GetScripts(ScriptType.JS);
                foreach (KeyValuePair<int, string> kvp in layoutElements)
                {
                    jsonJSs.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\" : \"{0}\",\"Name\" : \"{1}\"}}", kvp.Key, kvp.Value));
                }

                IList<UserControlAsset> m = UserControlAsset.GetModules(UserControlArea.Main);
                for (int i = 0; i < m.Count; i++)
                {
                    jsonMMods.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\" : \"{0}\",\"Name\" : \"{1}\"}}", m[i].ModuleId, m[i].ModuleName));
                }

                m = UserControlAsset.GetModules(UserControlArea.Right);
                for (int i = 0; i < m.Count; i++)
                {
                    jsonRMods.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\" : \"{0}\",\"Name\" : \"{1}\"}}", m[i].ModuleId, m[i].ModuleName));
                }
                
                for (int i = 0; i < p.MainModules.Count; i++)
                {
                    jsonPMMods.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\": \"{0}\", \"Order\": \"{1}\", \"Name\": \"{2}\"}}", p.MainModules[i].ModuleId, i + 1, p.MainModules[i].ModuleName));
                }

                for (int i = 0; i < p.RightModules.Count; i++)
                {
                    jsonPRMods.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\": \"{0}\", \"Order\": \"{1}\", \"Name\": \"{2}\"}}", p.RightModules[i].ModuleId, i + 1, p.RightModules[i].ModuleName));
                }

                IList<NavigationGroup> topNavs = NavigationGroup.GetNavigationGroups(NavigationGroupArea.Top);
                for (int i = 0; i < topNavs.Count; i++)
                {
                    jsonTopNavs.Add("{\"Name\": \"" + topNavs[i].Name + "\"}");
                }

                IList<NavigationGroup> leftNavs = NavigationGroup.GetNavigationGroups(NavigationGroupArea.Left);
                for (int i = 0; i < leftNavs.Count; i++)
                {
                    jsonLeftNavs.Add("{\"Name\": \"" + leftNavs[i].Name + "\"}");
                }

                IList<NavigationGroup> pageTopNavs = p.GetNavigationGroups(NavigationGroupArea.Top);
                for (int i = 0; i < pageTopNavs.Count; i++)
                {
                    jsonPTopNavs.Add("{\"Order\": \"" + i + "\", \"Name\": \"" + pageTopNavs[i].Name + "\"}");
                }

                IList<NavigationGroup> pageLeftNavs = p.GetNavigationGroups(NavigationGroupArea.Left);
                for (int i = 0; i < pageLeftNavs.Count; i++)
                {
                    jsonPLeftNavs.Add("{\"Order\": \"" + i + "\", \"Name\": \"" + pageLeftNavs[i].Name + "\"}");
                }

                IList<Content> contents = p.GetPageContentVersionsInfo();
                for (int i = 0; i < contents.Count; i++)
                {
                    if (contents[i].Author != null)
                    {
                        jsonVersions.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\": \"{0}\", \"CreatedDate\": \"{1}\", \"Author\": \"{2}\"}}", new object[] { contents[i].ContentId, contents[i].Created, contents[i].Author.UserName }));
                    }
                    else
                    {
                        jsonVersions.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\": \"{0}\", \"CreatedDate\": \"{1}\", \"Author\": \"[Deleted User]\"}}", new object[] { contents[i].ContentId, contents[i].Created }));
                    }
                }
                
                context.Response.Write("[{ " + output + ", \"Headers\" : [" + string.Join(", ", jsonHeaders.ToArray()) + "], \"Footers\" : [" + string.Join(", ", jsonFooters.ToArray()) + "], \"CSSs\" : [" + string.Join(", ", jsonCSSs.ToArray()) + "], \"JSs\" : [" + string.Join(", ", jsonJSs.ToArray()) + "], \"TopNavs\" : [" + string.Join(", ", jsonTopNavs.ToArray()) + "], \"LeftNavs\" : [" + string.Join(", ", jsonLeftNavs.ToArray()) + "], \"RMods\" : [" + string.Join(", ", jsonRMods.ToArray()) + "], \"MMods\" : [" + string.Join(", ", jsonMMods.ToArray()) + "], \"pVersions\" : [" + string.Join(", ", jsonVersions.ToArray()) + "], \"pMMods\" : [" + string.Join(", ", jsonPMMods.ToArray()) + "], \"pRMods\" : [" + string.Join(", ", jsonPRMods.ToArray()) + "], \"pTopNavs\" : [" + string.Join(", ", jsonPTopNavs.ToArray()) + "], \"pLeftNavs\" : [" + string.Join(", ", jsonPLeftNavs.ToArray()) + "]}]");
            }
            else
            {
                context.Response.Write("Page settings retrieval failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to append an item to a top navigation group.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void AddTopNavItem(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string group = context.Request["group"];
                string text = context.Request["text"];
                string order = context.Request["order"];
                string link = context.Request["link"];
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.InsertTopNav", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@NavItemLink", link);
                        cmd.Parameters.AddWithValue("@NavItemText", text);
                        cmd.Parameters.AddWithValue("@NavItemOrder", order);
                        cmd.Parameters.AddWithValue("@NavItemGroup", group);
                        cmd.ExecuteNonQuery();
                    }
                }

                context.Response.Write("Successfully added top navigation item.");
            }
            else
            {
                context.Response.Write("Top navigation creation failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to remove an item from a top navigation group.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void DeleteTopNavItem(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string navName = context.Request["navName"];
                string itemID = context.Request["itemID"];
                string ordinal = context.Request["ordinal"];
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.DeleteTopNav", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@NavItemID", itemID);
                        cmd.Parameters.AddWithValue("@NavItemOrder", ordinal);
                        cmd.Parameters.AddWithValue("@NavItemGroup", navName);
                        cmd.ExecuteNonQuery();
                    }
                }

                context.Response.Write("Successfully deleted top navigation item.");
            }
            else
            {
                context.Response.Write("Top navigation deletion failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to update the order of items in a top navigation group.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdateTopNavItemOrder(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                int itemId = 0;
                int oldOrdinal = 0;
                int newOrdinal = 0;
                if (int.TryParse(context.Request["itemID"], out itemId) && int.TryParse(context.Request["oldOrdinal"], out oldOrdinal) && int.TryParse(context.Request["newOrdinal"], out newOrdinal))
                {
                    string navName = context.Request["navName"];
                    using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                    {
                        conn.Open();
                        if (oldOrdinal > newOrdinal)
                        {
                            using (SqlCommand cmd = new SqlCommand("Lidocaine.UpdateTopNavOrder", conn))
                            {
                                cmd.CommandType = CommandType.StoredProcedure;
                                cmd.Parameters.AddWithValue("@ID", itemId);
                                cmd.Parameters.AddWithValue("@OrderNew", newOrdinal);
                                cmd.Parameters.AddWithValue("@OrderOld", oldOrdinal);
                                cmd.Parameters.AddWithValue("@NavItemGroup", navName);
                                cmd.ExecuteNonQuery();
                            }
                        }
                        else if (oldOrdinal < newOrdinal)
                        {
                            using (SqlCommand cmd = new SqlCommand("Lidocaine.UpdateTopNavOrder2", conn))
                            {
                                cmd.CommandType = CommandType.StoredProcedure;
                                cmd.Parameters.AddWithValue("@ID", itemId);
                                cmd.Parameters.AddWithValue("@OrderNew", newOrdinal);
                                cmd.Parameters.AddWithValue("@OrderOld", oldOrdinal);
                                cmd.Parameters.AddWithValue("@NavItemGroup", navName);
                                cmd.ExecuteNonQuery();
                            }
                        }
                    }

                    context.Response.Write("Successfully reordered top navigation group.");
                }
                else
                {
                    context.Response.Write("Page top navigation update failed: One or more parameters not valid.");
                }
            }
            else
            {
                context.Response.Write("Top navigation update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to select a list of items in a top navigation group.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void EditTopNav(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string navName = context.Request["navName"];
                List<string> jsonPages = new List<string>();
                List<string> jsonItems = new List<string>();
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.GetTopNavPages", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@Name", navName);
                        using (SqlDataReader rdr = cmd.ExecuteReader())
                        {
                            if (rdr.HasRows)
                            {
                                while (rdr.Read())
                                {
                                    jsonPages.Add("{\"Name\": \"" + rdr["Name"].ToString() + "\"}");
                                }
                            }
                        }
                    }

                    using (SqlCommand cmd = new SqlCommand("Lidocaine.GetTopNavInfo", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@Name", navName);
                        using (SqlDataReader rdr = cmd.ExecuteReader())
                        {
                            if (rdr.HasRows)
                            {
                                while (rdr.Read())
                                {
                                    jsonItems.Add("{\"Order\": \"" + rdr["Order"].ToString() + "\", \"URL\": \"" + rdr["Link"].ToString() + "\", \"Text\": \"" + EscapeJSON(rdr["Text"].ToString()) + "\", \"ID\": \"" + rdr["ID"].ToString() + "\"}");
                                }
                            }
                        }
                    }
                }

                context.Response.Write("[{ \"Pages\" : [" + string.Join(", ", jsonPages.ToArray()) + "], \"Items\" : [" + string.Join(", ", jsonItems.ToArray()) + "]}]");
            }
            else
            {
                context.Response.Write("Top navigation retrieval failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to append an item to a left navigation group.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void AddLeftNavItem(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string group = context.Request["group"];
                string text = context.Request["text"];
                string order = context.Request["order"];
                string link = context.Request["link"];
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.InsertLeftNav", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@NavItemLink", link);
                        cmd.Parameters.AddWithValue("@NavItemText", text);
                        cmd.Parameters.AddWithValue("@NavItemOrder", order);
                        cmd.Parameters.AddWithValue("@NavItemGroup", group);
                        cmd.ExecuteNonQuery();
                    }
                }

                context.Response.Write("Successfully added left navigation item.");
            }
            else
            {
                context.Response.Write("Left navigation creation failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to remove an item from a left navigation group.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void DeleteLeftNavItem(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string navName = context.Request["navName"];
                string itemID = context.Request["itemID"];
                string ordinal = context.Request["ordinal"];
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.DeleteLeftNav", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@NavItemID", itemID);
                        cmd.Parameters.AddWithValue("@NavItemOrder", ordinal);
                        cmd.Parameters.AddWithValue("@NavItemGroup", navName);
                        cmd.ExecuteNonQuery();
                    }
                }

                context.Response.Write("Successfully deleted left navigation item.");
            }
            else
            {
                context.Response.Write("Left navigation deletion failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to update the order of items in a left navigation group.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdateLeftNavItemOrder(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                int oldOrdinal = 0;
                int newOrdinal = 0;
                if (int.TryParse(context.Request["oldOrdinal"], out oldOrdinal) && int.TryParse(context.Request["newOrdinal"], out newOrdinal))
                {
                    string navName = context.Request["navName"];
                    string itemID = context.Request["itemID"];
                    using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                    {
                        conn.Open();
                        if (oldOrdinal > newOrdinal)
                        {
                            using (SqlCommand cmd = new SqlCommand("Lidocaine.UpdateLeftNavOrder", conn))
                            {
                                cmd.CommandType = CommandType.StoredProcedure;
                                cmd.Parameters.AddWithValue("@ID", itemID);
                                cmd.Parameters.AddWithValue("@OrderNew", newOrdinal);
                                cmd.Parameters.AddWithValue("@OrderOld", oldOrdinal);
                                cmd.Parameters.AddWithValue("@NavItemGroup", navName);
                                cmd.ExecuteNonQuery();
                            }
                        }
                        else if (oldOrdinal < newOrdinal)
                        {
                            using (SqlCommand cmd = new SqlCommand("Lidocaine.UpdateLeftNavOrder2", conn))
                            {
                                cmd.CommandType = CommandType.StoredProcedure;
                                cmd.Parameters.AddWithValue("@ID", itemID);
                                cmd.Parameters.AddWithValue("@OrderNew", newOrdinal);
                                cmd.Parameters.AddWithValue("@OrderOld", oldOrdinal);
                                cmd.Parameters.AddWithValue("@NavItemGroup", navName);
                                cmd.ExecuteNonQuery();
                            }
                        }
                    }

                    context.Response.Write("Successfully reordered left navigation group.");
                }
                else
                {
                    context.Response.Write("Left navigation update failed: Identifier parameter failed.");
                }
            }
            else
            {
                context.Response.Write("Left navigation update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to select a list of items in a left navigation group.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void EditLeftNav(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string navName = context.Request["navName"];
                List<string> jsonPages = new List<string>();
                List<string> jsonItems = new List<string>();
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.GetLeftNavPages", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@Name", navName);
                        using (SqlDataReader rdr = cmd.ExecuteReader())
                        {
                            if (rdr.HasRows)
                            {
                                while (rdr.Read())
                                {
                                    jsonPages.Add("{\"Name\": \"" + rdr["Name"].ToString() + "\"}");
                                }
                            }
                        }
                    }

                    using (SqlCommand cmd = new SqlCommand("Lidocaine.GetLeftNavInfo", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@Name", navName);
                        using (SqlDataReader rdr = cmd.ExecuteReader())
                        {
                            if (rdr.HasRows)
                            {
                                while (rdr.Read())
                                {
                                    jsonItems.Add("{\"Order\": \"" + rdr["Order"].ToString() + "\", \"URL\": \"" + rdr["Link"].ToString() + "\", \"Text\": \"" + EscapeJSON(rdr["Text"].ToString()) + "\", \"ID\": \"" + rdr["ID"].ToString() + "\"}");
                                }
                            }
                        }
                    }
                }

                context.Response.Write("[{ \"Pages\" : [" + string.Join(", ", jsonPages.ToArray()) + "], \"Items\" : [" + string.Join(", ", jsonItems.ToArray()) + "]}]");
            }
            else
            {
                context.Response.Write("Left navigation retrieval failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to save the changes made to a page's content and make the new version the current version.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void SaveAndPublishPage(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                string pageID = context.Request["pageID"];
                string pageContent = context.Request["content"];
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.UpdatePageContent", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@PageID", pageID);
                        cmd.Parameters.AddWithValue("@PageContent", pageContent);
                        cmd.Parameters.AddWithValue("@UserID", Profile.Current.UserId);
                        cmd.ExecuteNonQuery();
                    }
                }

                context.Response.Write("Page content successfully saved and published.");
            }
            else
            {
                context.Response.Write("Content update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to save the changes made to a page's content.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void SavePage(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager") || roles.Contains("Content Provider"))
            {
                string pageID = context.Request["pageID"];
                string pageContent = context.Request["content"];
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.InsertPageContent", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@PageID", pageID);
                        cmd.Parameters.AddWithValue("@PageContent", pageContent);
                        cmd.Parameters.AddWithValue("@UserID", Profile.Current.UserId);
                        cmd.ExecuteNonQuery();
                    }
                }

                context.Response.Write("Page content successfully saved.");
            }
            else
            {
                context.Response.Write("Content update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to select a page's current version content.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void EditPage(HttpContext context)
        {
            bool isAdmin = false;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager") || roles.Contains("Content Provider"))
            {
                if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
                {
                    isAdmin = true;
                }

                PageLayout p = new PageLayout(context.Request["pagePath"]);
                context.Response.Write("[{ \"IsAdmin\": \"" + (isAdmin ? "1" : "0") + "\", \"PageID\": \"" + p.PageId + "\", \"Content\": \"" + (p.Content != null ? EscapeJSON(p.Content.Html) : string.Empty) + "\" }]");
            }
            else
            {
                context.Response.Write("Content retrieval failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to create a left navigation group.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void AddLeftNav(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string navName = context.Request["name"];
                Regex myRegex = new Regex(@"^[\w]+$");
                if (myRegex.IsMatch(navName))
                {
                    bool navExists = true;
                    using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                    {
                        conn.Open();
                        using (SqlCommand cmd = new SqlCommand("Lidocaine.GetLeftNavItemByName", conn))
                        {
                            cmd.CommandType = CommandType.StoredProcedure;
                            cmd.Parameters.AddWithValue("@NavItemGroup", navName);
                            using (SqlDataReader rdr = cmd.ExecuteReader())
                            {
                                if (!rdr.HasRows)
                                {
                                    navExists = false;
                                }
                            }
                        }

                        if (!navExists)
                        {
                            using (SqlCommand cmd = new SqlCommand("Lidocaine.InsertLeftNavItem", conn))
                            {
                                cmd.CommandType = CommandType.StoredProcedure;
                                cmd.Parameters.AddWithValue("@NavItemGroup", navName);
                                cmd.ExecuteNonQuery();
                                output = "Successfully created left navigation group \"" + navName + "\".";
                            }
                        }
                    }

                    if (navExists)
                    {
                        output = "Creation failed: navigation group already exists.";
                    }
                }
                else
                {
                    output = "Creation failed: please use only alphanumeric characters.";
                }
            }
            else
            {
                context.Response.Write("Left navigation creation failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to select the items in a left navigation group.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void LoadLeftNav(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                DataTable dt = new DataTable();
                dt.Locale = CultureInfo.InvariantCulture;
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.GetLeftNavs", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        using (SqlDataReader rdr = cmd.ExecuteReader())
                        {
                            dt.Load(rdr);
                            context.Response.Write(GetJSONString(dt));
                        }
                    }
                }
            }
            else
            {
                context.Response.Write("Left navigation retrieval failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to create a top navigation group.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void AddTopNav(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string navName = context.Request["name"];
                Regex myRegex = new Regex(@"^[\w]+$");
                if (myRegex.IsMatch(navName))
                {
                    bool navExists = true;
                    using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                    {
                        conn.Open();
                        using (SqlCommand cmd = new SqlCommand("Lidocaine.GetTopNavItemByName", conn))
                        {
                            cmd.CommandType = CommandType.StoredProcedure;
                            cmd.Parameters.AddWithValue("@NavItemGroup", navName);
                            using (SqlDataReader rdr = cmd.ExecuteReader())
                            {
                                if (!rdr.HasRows)
                                {
                                    navExists = false;
                                }
                            }
                        }

                        if (!navExists)
                        {
                            using (SqlCommand cmd = new SqlCommand("Lidocaine.InsertTopNavItem", conn))
                            {
                                cmd.CommandType = CommandType.StoredProcedure;
                                cmd.Parameters.AddWithValue("@NavItemGroup", navName);
                                cmd.ExecuteNonQuery();
                                output = "Successfully created top navigation group \"" + navName + "\".";
                            }
                        }
                    }

                    if (navExists)
                    {
                        output = "Creation failed: navigation group already exists.";
                    }
                }
                else
                {
                    output = "Creation failed: please use only alphanumeric characters.";
                }
            }
            else
            {
                context.Response.Write("Top navigation creation failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to select the items in a top navigation group.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void LoadTopNav(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                DataTable dt = new DataTable();
                dt.Locale = CultureInfo.InvariantCulture;
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.GetTopNavs", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        using (SqlDataReader rdr = cmd.ExecuteReader())
                        {
                            dt.Load(rdr);
                            output = GetJSONString(dt);
                        }
                    }
                }
            }
            else
            {
                context.Response.Write("Top navigation retrieval failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to add a right column module.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void AddRModule(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string moduleName = context.Request["name"];
                Regex myRegex = new Regex(@"^[ \w\.]+$");
                if (myRegex.IsMatch(moduleName) && !string.IsNullOrWhiteSpace(moduleName))
                {
                    bool moduleExists = true;
                    IList<UserControlAsset> modules = UserControlAsset.GetModules(UserControlArea.Right);
                    for (int i = 0; i < modules.Count; i++)
                    {
                        if (modules[i].ModuleName == moduleName)
                        {
                            moduleExists = true;
                            break;
                        }
                    }

                    if (moduleExists)
                    {
                        context.Response.Write("Registration failed: module already registered.");
                    }
                    else
                    {
                        UserControlAsset m = new UserControlAsset();
                        m.ModuleType = UserControlArea.Right;
                        m.ModuleName = moduleName;
                        m.ModulePath = context.Request["path"];
                        m.Description = context.Request["description"];
                        m.SaveAs();
                        context.Response.Write("Registration successful.");
                    }
                }
                else
                {
                    context.Response.Write("Registration failed: please use only alphanumeric characters.");
                }
            }
            else
            {
                context.Response.Write("UserControl registration failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to remove a right column module.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void DeleteRModule(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                int moduleId = 0;
                if (int.TryParse(context.Request["moduleID"], out moduleId))
                {
                    UserControlAsset module = new UserControlAsset(moduleId);
                    module.Delete();
                    context.Response.Write("Successfully removed right module.");
                }
                else
                {
                    context.Response.Write("UserControl deregistration failed: Identifier parameter not valid." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
                }
            }
            else
            {
                context.Response.Write("UserControl deregistration failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>");
            }
        }

        /// <summary>
        /// Handles the request to select a list of right column modules.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void LoadRModules(HttpContext context)
        {
            List<string> output = new List<string>();
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                IList<UserControlAsset> m = UserControlAsset.GetModules(UserControlArea.Main);
                for (int i = 0; i < m.Count; i++)
                {
                    output.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\" : \"{0}\",\"Name\" : \"{1}\", \"Path\" : \"{2}\"}}", m[i].ModuleId, m[i].ModuleName, m[i].ModulePath));
                }

                context.Response.Write("[" + string.Join(", ", output.ToArray()) + "]");
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }
        }

        /// <summary>
        /// Handles the request to add a main column module.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void AddMModule(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string moduleName = context.Request["name"];
                Regex myRegex = new Regex(@"^[ \w\.]+$");
                if (myRegex.IsMatch(moduleName) && !string.IsNullOrWhiteSpace(moduleName))
                {
                    bool moduleExists = false;
                    IList<UserControlAsset> modules = UserControlAsset.GetModules(UserControlArea.Main);
                    for (int i = 0; i < modules.Count; i++)
                    {
                        if (modules[i].ModuleName == moduleName)
                        {
                            moduleExists = true;
                            break;
                        }
                    }

                    if (moduleExists)
                    {
                        output = "Registration failed: module already registered.";
                    }
                    else
                    {
                        UserControlAsset m = new UserControlAsset();
                        m.ModuleType = UserControlArea.Main;
                        m.ModuleName = moduleName;
                        m.ModulePath = context.Request["path"];
                        m.Description = context.Request["description"];
                        m.SaveAs();
                        output = "Registration successful.";
                    }
                }
                else
                {
                    output = "Registration failed: please use only alphanumeric characters and spaces. Do not name the module a series of spaces.";
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to delete a main column module.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void DeleteMModule(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string moduleID = context.Request["moduleID"];
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.DeleteModule", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@ModuleID", moduleID);
                        cmd.ExecuteNonQuery();
                        output = "Successfully removed main module.";
                    }
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to select a list of main column modules.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void LoadMModules(HttpContext context)
        {
            List<string> output = new List<string>();
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                IList<UserControlAsset> m = UserControlAsset.GetModules(UserControlArea.Main);
                for (int i = 0; i < m.Count; i++)
                {
                    output.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\" : \"{0}\",\"Name\" : \"{1}\", \"Path\" : \"{2}\"}}", m[i].ModuleId, m[i].ModuleName, m[i].ModulePath));
                }

                context.Response.Write("[" + string.Join(", ", output.ToArray()) + "]");
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }
        }

        /// <summary>
        /// Handles the request to update a style sheet.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdateCss(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                int scriptId = 0;
                if (int.TryParse(context.Request["cssID"], out scriptId))
                {
                    Script s = new Script(scriptId);
                    s.ScriptText = context.Request["content"];
                    s.Save();
                    context.Response.Write("CSS script content successfully updated.");
                }
                else
                {
                    context.Response.Write("Script update failed: Identifier parameter not valid.");
                }
            }
            else
            {
                context.Response.Write("User does not have privileges to save edits to CSS scripts.");
            }
        }

        /// <summary>
        /// Handles the request to select style sheet info for editing.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void EditCss(HttpContext context)
        {
            bool isAdmin = false;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                isAdmin = true;
                Script s = new Script(Convert.ToInt32(context.Request["cssID"], CultureInfo.InvariantCulture));
                IList<string> pages = s.GetPages();
                string[] jsonPages = new string[pages.Count];
                for (int i = 0; i < pages.Count; i++)
                {
                    jsonPages[i] = "{\"Name\": \"" + pages[i] + "\"}";
                }

                context.Response.Write("[{ \"IsAdmin\": \"" + (isAdmin ? "1" : "0") + "\", \"Content\": \"" + EscapeJSON(s.ScriptText) + "\", \"Pages\" : [" + string.Join(", ", jsonPages) + "]}]");
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }
        }

        /// <summary>
        /// Handles the request to add a new style sheet.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void AddCss(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string scriptName = context.Request["name"];
                Regex myRegex = new Regex(@"^[\w]+$");
                if (myRegex.IsMatch(scriptName))
                {
                    Dictionary<int, string> scripts = Script.GetScripts(ScriptType.Css);
                    if (!scripts.ContainsValue(scriptName))
                    {
                        Script s = new Script();
                        s.ScriptName = scriptName;
                        s.ScriptType = ScriptType.Css;
                        s.SaveAs();
                        output = "Successfully created CSS script \"" + scriptName + "\".";
                    }
                    else
                    {
                        output = "Creation failed: CSS script name already exists.";
                    }
                }
                else
                {
                    output = "Creation failed: please use only alphanumeric characters.";
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to rename a style sheet.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void RenameCss(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                int scriptID = 0;
                if (int.TryParse(context.Request["scriptID"], out scriptID))
                {
                    string newName = context.Request["name"];
                    string existingName = context.Request["existingName"];
                    Regex myRegex = new Regex(@"^[\w]+$");
                    if (myRegex.IsMatch(newName))
                    {
                        Dictionary<int, string> scripts = Script.GetScripts(ScriptType.Css);
                        if (!scripts.ContainsValue(newName))
                        {
                            Script s = new Script(scriptID);
                            s.ScriptName = newName;
                            s.Save();
                            output = "Successfully renamed CSS script \"" + existingName + "\" to \"" + newName + "\".";
                        }
                        else
                        {
                            output = "Script update failed: Another CSS script with this name already exists.";
                        }
                    }
                    else
                    {
                        output = "Script update failed: Please use only alphanumeric characters.";
                    }
                }
                else
                {
                    output = "Script update failed: Script identifier parameter not valid.";
                }
            }
            else
            {
                output = "Script update failed: User not authorized." + " <a href=\"" + Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/\">" + "Click here to reauthenticate." + "</a>";
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to select a list of style sheets.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void LoadCss(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                Dictionary<int, string> dic = Script.GetScripts(ScriptType.Css);
                List<string> json = new List<string>();
                foreach (KeyValuePair<int, string> kvp in dic)
                {
                    json.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\" : \"{0}\",\"Name\" : \"{1}\"}}", kvp.Key, kvp.Value));
                }

                output = "[" + string.Join(",", json.ToArray()) + "]";
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to update a javascript.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdateJs(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                int scriptId = 0;
                if (int.TryParse(context.Request["jsID"], out scriptId))
                {
                    Script s = new Script(scriptId);
                    s.ScriptText = context.Request["content"];
                    s.Save();
                    context.Response.Write("Javascript content successfully updated.");
                }
                else
                {
                    context.Response.Write("Script update failed: Identifier parameter not valid.");
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }
        }

        /// <summary>
        /// Handles the request to select javascript info for editing.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void EditJs(HttpContext context)
        {
            bool isAdmin = false;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                isAdmin = true;
                string javascriptID = context.Request["jsID"];
                Script s = new Script(Convert.ToInt32(javascriptID, CultureInfo.InvariantCulture));
                IList<string> pages = s.GetPages();
                string[] jsonPages = new string[pages.Count];
                for (int i = 0; i < pages.Count; i++)
                {
                    jsonPages[i] = "{\"Name\": \"" + pages[i] + "\"}";
                }

                context.Response.Write("[{ \"IsAdmin\": \"" + (isAdmin ? "1" : "0") + "\", \"Content\": \"" + EscapeJSON(s.ScriptText) + "\", \"Pages\" : [" + string.Join(", ", jsonPages) + "]}]");
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }
        }

        /// <summary>
        /// Handles the request to add a javascript.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void AddJs(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string scriptName = context.Request["name"];
                Regex myRegex = new Regex(@"^[\w]+$");
                if (myRegex.IsMatch(scriptName))
                {
                    Dictionary<int, string> scripts = Script.GetScripts(ScriptType.JS);
                    if (!scripts.ContainsValue(scriptName))
                    {
                        Script s = new Script();
                        s.ScriptName = scriptName;
                        s.ScriptType = ScriptType.JS;
                        s.SaveAs();
                        output = "Successfully created Javascript \"" + scriptName + "\".";
                    }
                    else
                    {
                        output = "Creation failed: Javascript name already exists.";
                    }
                }
                else
                {
                    output = "Creation failed: please use only alphanumeric characters.";
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to delete a script.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void DeleteScript(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                Script s = new Script(Convert.ToInt32(context.Request["scriptID"], CultureInfo.InvariantCulture));
                output = s.ScriptType == ScriptType.Css ? "stylesheet" : "javascript";
                s.Delete();
                output = "Successfully deleted " + output + ".";
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to rename a javascript.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void RenameJs(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                int scriptId = 0;
                if (int.TryParse(context.Request["scriptID"], out scriptId))
                {
                    string newName = context.Request["name"];
                    string existingName = context.Request["existingName"];
                    Regex myRegex = new Regex(@"^[\w]+$");
                    if (myRegex.IsMatch(newName))
                    {
                        Dictionary<int, string> scripts = Script.GetScripts(ScriptType.JS);
                        if (!scripts.ContainsValue(newName))
                        {
                            Script s = new Script(scriptId);
                            s.ScriptName = newName;
                            s.Save();
                            output = "Successfully renamed Javascript \"" + existingName + "\" to \"" + newName + "\".";
                        }
                        else
                        {
                            output = "Rename failed.  Another Javascript with this name already exists.";
                        }
                    }
                    else
                    {
                        output = "Rename failed.  Please use only alphanumeric characters.";
                    }
                }
                else
                {
                    output = "Rename failed. Identifier parameter not valid.";
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to select a list of javascripts.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void LoadJs(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                Dictionary<int, string> dic = Script.GetScripts(ScriptType.JS);
                List<string> json = new List<string>();
                foreach (KeyValuePair<int, string> kvp in dic)
                {
                    json.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\" : \"{0}\",\"Name\" : \"{1}\"}}", kvp.Key, kvp.Value));
                }

                output = "[" + string.Join(",", json.ToArray()) + "]";
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to update header script content.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdateHeader(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                int headerId = 0;
                if (int.TryParse(context.Request["headerID"], out headerId))
                {
                    Template t = new Template(headerId);
                    t.TemplateText = context.Request["content"];
                    t.Save();
                    context.Response.Write("Header content successfully updated.");
                }
                else
                {
                    context.Response.Write("Header update failed: Identifier parameter not valid.");
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }
        }

        /// <summary>
        /// Handles the request to retrieve header contents for editing.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void EditHeader(HttpContext context)
        {
            bool isAdmin = false;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                isAdmin = true;
                int headerId = 0;
                if (int.TryParse(context.Request["headerID"], out headerId))
                {
                    Template t = new Template(headerId);
                    IList<string> pages = t.GetPages();
                    string[] jsonPages = new string[pages.Count];
                    for (int i = 0; i < pages.Count; i++)
                    {
                        jsonPages[i] = "{\"Name\": \"" + pages[i] + "\"}";
                    }

                    context.Response.Write("[{ \"IsAdmin\": \"" + (isAdmin ? "1" : "0") + "\", \"Content\": \"" + EscapeJSON(t.TemplateText) + "\", \"Pages\" : [" + string.Join(", ", jsonPages) + "]}]");
                }
                else
                {
                    context.Response.Write("Header retrieval failed: Identifier parameter not valid.");
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }
        }

        /// <summary>
        /// Handles the request to add a new header template script to the application.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void AddHeader(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string headerName = context.Request["name"];
                Regex myRegex = new Regex(@"^[\w]+$");
                if (myRegex.IsMatch(headerName))
                {
                    Dictionary<int, string> templates = Template.GetTemplates(TemplateArea.Header);
                    if (!templates.ContainsValue(headerName))
                    {
                        Template t = new Template();
                        t.TemplateName = headerName;
                        t.TemplateType = TemplateArea.Header;
                        t.SaveAs();
                        output = "Successfully created header \"" + headerName + "\".";
                    }
                    else
                    {
                        output = "Creation failed: header already exists.";
                    }
                }
                else
                {
                    output = "Creation failed: please use only alphanumeric characters.";
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to delete template header or footer objects from this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void DeleteTemplate(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                Template t = new Template(Convert.ToInt32(context.Request["templateID"], CultureInfo.InvariantCulture));
                output = t.TemplateType == TemplateArea.Header ? "header" : "footer";
                t.Delete();
                output = "Successfully deleted " + output + ".";
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to rename a template header object in this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void RenameHeader(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                int headerId = 0;
                if (int.TryParse(context.Request["headerID"], out headerId))
                {
                    string newName = context.Request["name"];
                    string existingName = context.Request["existingName"];
                    Regex myRegex = new Regex(@"^[\w]+$");
                    if (myRegex.IsMatch(newName))
                    {
                        Dictionary<int, string> templates = Template.GetTemplates(TemplateArea.Header);
                        if (!templates.ContainsValue(newName))
                        {
                            Template t = new Template(headerId);
                            t.TemplateName = newName;
                            t.Save();
                            output = "Successfully renamed header \"" + existingName + "\" to \"" + newName + "\".";
                        }
                        else
                        {
                            output = "Rename failed.  Another header with this name already exists.";
                        }
                    }
                    else
                    {
                        output = "Rename failed.  Please use only alphanumeric characters.";
                    }
                }
                else
                {
                    output = "Rename failed. Identifier parameter not valid.";
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to list the template header objects associated with this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void LoadHeaders(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                Dictionary<int, string> dic = Template.GetTemplates(TemplateArea.Header);
                List<string> json = new List<string>();
                foreach (KeyValuePair<int, string> kvp in dic)
                {
                    json.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\" : \"{0}\",\"Name\" : \"{1}\"}}", kvp.Key, kvp.Value));
                }

                output = "[" + string.Join(",", json.ToArray()) + "]";
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to update a template footer object's contents.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void UpdateFooter(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                int footerId = 0;
                if (int.TryParse(context.Request["footerID"], out footerId))
                {
                    Template t = new Template(footerId);
                    t.TemplateText = context.Request["content"];
                    t.Save();
                    context.Response.Write("Footer content successfully updated.");
                }
                else
                {
                    context.Response.Write("Footer update failed: Identifier parameter not valid.");
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }
        }

        /// <summary>
        /// Handles the request for a template footer object's contents for editing.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void EditFooter(HttpContext context)
        {
            bool isAdmin = false;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                isAdmin = true;
                int footerId = 0;
                if (int.TryParse(context.Request["footerID"], out footerId))
                {
                    Template t = new Template(footerId);
                    IList<string> pages = t.GetPages();
                    string[] jsonPages = new string[pages.Count];
                    for (int i = 0; i < pages.Count; i++)
                    {
                        jsonPages[i] = "{\"Name\": \"" + pages[i] + "\"}";
                    }

                    context.Response.Write("[{ \"IsAdmin\": \"" + (isAdmin ? "1" : "0") + "\", \"Content\": \"" + EscapeJSON(t.TemplateText) + "\", \"Pages\" : [" + string.Join(", ", jsonPages) + "]}]");
                }
                else
                {
                    context.Response.Write("Footer retrieval failed: Identifier parameter not valid.");
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }
        }

        /// <summary>
        /// Handles a request to add a template footer object to this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void AddFooter(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                string footerName = context.Request["name"];
                Regex myRegex = new Regex(@"^[\w]+$");
                if (myRegex.IsMatch(footerName))
                {
                    Dictionary<int, string> templates = Template.GetTemplates(TemplateArea.Footer);
                    if (!templates.ContainsValue(footerName))
                    {
                        Template t = new Template();
                        t.TemplateName = footerName;
                        t.TemplateType = TemplateArea.Footer;
                        t.SaveAs();
                        output = "Successfully created footer \"" + footerName + "\".";
                    }
                    else
                    {
                        output = "Creation failed: footer already exists.";
                    }
                }
                else
                {
                    output = "Creation failed: please use only alphanumeric characters.";
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to rename a template footer object in this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void RenameFooter(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                int footerId = 0;
                if (int.TryParse(context.Request["footerID"], out footerId))
                {
                    string newName = context.Request["name"];
                    string existingName = context.Request["existingName"];
                    Regex myRegex = new Regex(@"^[\w]+$");
                    if (myRegex.IsMatch(newName))
                    {
                        Dictionary<int, string> templates = Template.GetTemplates(TemplateArea.Footer);
                        if (!templates.ContainsValue(newName))
                        {
                            Template t = new Template(footerId);
                            t.TemplateName = newName;
                            t.Save();
                            output = "Successfully renamed footer \"" + existingName + "\" to \"" + newName + "\".";
                        }
                        else
                        {
                            output = "Rename failed.  Another footer with this name already exists.";
                        }
                    }
                    else
                    {
                        output = "Rename failed.  Please use only alphanumeric characters.";
                    }
                }
                else
                {
                    output = "Rename failed. Identifier parameter not valid.";
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request for the template footer objects associated with this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void LoadFooters(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                Dictionary<int, string> dic = Template.GetTemplates(TemplateArea.Footer);
                List<string> json = new List<string>();
                foreach (KeyValuePair<int, string> kvp in dic)
                {
                    json.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ID\" : \"{0}\",\"Name\" : \"{1}\"}}", kvp.Key, kvp.Value));
                }

                output = "[" + string.Join(",", json.ToArray()) + "]";
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles a request to list the users associated with this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void LoadUsers(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                DataTable dt = new DataTable();
                dt.Locale = CultureInfo.InvariantCulture;
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.GetUsersIDsAndUserNames", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        using (SqlDataReader rdr = cmd.ExecuteReader())
                        {
                            dt.Load(rdr);
                            output = GetJSONString(dt);
                        }
                    }
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to delete user objects from this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void DeleteUser(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator"))
            {
                Profile profile = new Profile(Convert.ToInt32(context.Request["userID"], CultureInfo.InvariantCulture));
                profile.Delete();
                output = "Successfully deleted user.";
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to update a user.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void UpdateUser(HttpContext context)
        {
            List<string> output = new List<string>();
            IList<string> roles = Profile.Current.Roles;
            if (!roles.Contains("Site Administrator"))
            {
                output.Add("<li>You have insufficient privileges to perform this action.</li>");
            }

            int userId = 0;
            if (!int.TryParse(context.Request["userID"], out userId))
            {
                output.Add("<li>User ID parameter invalid. It must be an integer.</li>");
            }

            if (string.IsNullOrEmpty(context.Request["username"]))
            {
                output.Add("<li>User Name parameter invalid. It was not found.</li>");
            }

            if (string.IsNullOrEmpty(context.Request["password"]))
            {
                output.Add("<li>Password parameter invalid. It was not found.</li>");
            }

            if (output.Count == 0)
            {
                Profile profile = new Profile(userId);
                profile.UserName = context.Request["username"];
                profile.Password = Profile.EncodePassword(context.Request["password"]);
                profile.Save();
                output.Add("Successfully updated user.");
            }

            context.Response.Write(string.Join("</li><li>", output.ToArray()));
        }

        /// <summary>
        /// Handles the request to insert a user.
        /// </summary>
        /// <param name="context">The HttpContext sent with the request.</param>
        private void AddUser(HttpContext context)
        {
            List<string> output = new List<string>();
            IList<string> roles = Profile.Current.Roles;
            if (!roles.Contains("Site Administrator"))
            {
                output.Add("<li>You have insufficient privileges to perform this action.</li>");
            }

            if (string.IsNullOrEmpty(context.Request["username"]))
            {
                output.Add("<li>User Name parameter invalid. It was not found.</li>");
            }

            if (string.IsNullOrEmpty(context.Request["password"]))
            {
                output.Add("<li>Password parameter invalid. It was not found.</li>");
            }

            if (output.Count == 0)
            {
                Profile profile = new Profile();
                profile.UserName = context.Request["username"];
                profile.Password = Profile.EncodePassword(context.Request["password"]);
                profile.SaveAs();
                output.Add("Successfully added user.");
            }

            context.Response.Write(string.Join("</li><li>", output.ToArray()));
        }

        /// <summary>
        /// Handles a request to list the groups associated with this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void LoadGroups(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                DataTable dt = new DataTable();
                dt.Locale = CultureInfo.InvariantCulture;
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.GetGroups", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        using (SqlDataReader rdr = cmd.ExecuteReader())
                        {
                            dt.Load(rdr);
                            output = GetJSONString(dt);
                        }
                    }
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles a request to rename a file object in this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void RenameFile(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                string path = string.IsNullOrEmpty(context.Request["path"]) ? string.Empty : context.Request["path"] + "/";
                string fileName = context.Request["name"];
                string existingPath = context.Request["existingPath"];
                Regex myRegex = new Regex(@"^[\w]+$");
                if (myRegex.IsMatch(fileName))
                {
                    Asset f = Asset.GetFileByVirtualPath(path + fileName);
                    if (f != null)
                    {
                        f = Asset.GetFileByVirtualPath(existingPath);
                        f.VirtualPath = path + fileName;
                        f.Save();
                        output = "Successfully renamed file \"" + fileName + "\".";
                    }
                    else
                    {
                        output = "Rename failed.  Another file with this name already exists.";
                    }
                }
                else
                {
                    output = "Rename failed.  Please use only alphanumeric characters.";
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to rename a page object in this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void RenamePage(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                string path = string.IsNullOrEmpty(context.Request["path"]) ? string.Empty : context.Request["path"] + "/";
                string pageName = context.Request["name"];
                string existingPath = context.Request["existingPath"];
                Regex myRegex = new Regex(@"^[\w]+$");
                if (myRegex.IsMatch(pageName))
                {
                    bool pageExists = true;
                    using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                    {
                        conn.Open();
                        using (SqlCommand cmd = new SqlCommand("Lidocaine.GetPageIDFromPagePath", conn))
                        {
                            cmd.CommandType = CommandType.StoredProcedure;
                            cmd.Parameters.AddWithValue("@PagePath", path + pageName + ".aspx");
                            using (SqlDataReader rdr = cmd.ExecuteReader())
                            {
                                if (!rdr.HasRows)
                                {
                                    pageExists = false;
                                }
                            }
                        }

                        if (!pageExists)
                        {
                            using (SqlCommand cmd = new SqlCommand("Lidocaine.RenamePage", conn))
                            {
                                cmd.CommandType = CommandType.StoredProcedure;
                                cmd.Parameters.AddWithValue("@NewPagePath", path + pageName + ".aspx");
                                cmd.Parameters.AddWithValue("@OrigPagePath", existingPath);
                                cmd.ExecuteNonQuery();
                            }

                            output = "Successfully renamed page \"" + pageName + ".aspx\".";
                        }
                    }

                    if (pageExists)
                    {
                        output = "Rename failed.  Another page with this name already exists.";
                    }
                }
                else
                {
                    output = "Rename failed.  Please use only alphanumeric characters.";
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to rename a folder object in this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void RenameFolder(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                string path = string.IsNullOrEmpty(context.Request["path"]) ? string.Empty : context.Request["path"] + "/";
                string folderName = context.Request["name"];
                string existingPath = context.Request["existingPath"];
                Regex myRegex = new Regex(@"^[\w]+$");
                if (myRegex.IsMatch(folderName))
                {
                    bool folderExists = true;
                    using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                    {
                        conn.Open();
                        using (SqlCommand cmd = new SqlCommand("Lidocaine.GetFolderIDFromFolderPath", conn))
                        {
                            cmd.CommandType = CommandType.StoredProcedure;
                            cmd.Parameters.AddWithValue("@FolderPath", path + folderName);
                            using (SqlDataReader rdr = cmd.ExecuteReader())
                            {
                                if (!rdr.HasRows)
                                {
                                    folderExists = false;
                                }
                            }
                        }

                        if (!folderExists)
                        {
                            using (SqlCommand cmd = new SqlCommand("Lidocaine.RenameFolder", conn))
                            {
                                cmd.CommandType = CommandType.StoredProcedure;
                                cmd.Parameters.AddWithValue("@NewFolderPath", path + folderName);
                                cmd.Parameters.AddWithValue("@OrigFolderPath", existingPath);
                                cmd.Parameters.AddWithValue("@PathRoot", existingPath + "/%");
                                cmd.ExecuteNonQuery();
                            }

                            output = "Successfully renamed folder \"" + folderName + "\".";
                        }
                    }

                    if (folderExists)
                    {
                        output = "Rename failed.  Another folder with this name already exists.";
                    }
                }
                else
                {
                    output = "Rename failed.  Please use only alphanumeric characters.";
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to delete a file object from this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void DeleteFile(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                string filePath = context.Request["path"];
                Asset f = Asset.GetFileByVirtualPath(filePath);
                FileInfo fi = new FileInfo(Environmental.StaticFilesDirectory + f.FilePath);
                fi.Delete();
                f.Delete();
                output = "Successfully deleted file \"/" + filePath + "\".";
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to delete a page object from this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void DeletePage(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                string pagePath = context.Request["path"];
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.DeletePage", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@PagePath", pagePath);
                        cmd.ExecuteNonQuery();
                        output = "Successfully deleted page \"/" + pagePath + "\".";
                    }
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to delete a folder object and all of its child objects from this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void DeleteFolder(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                string folderPath = context.Request["path"];
                DataTable dt = new DataTable();
                dt.Locale = CultureInfo.InvariantCulture;
                FileInfo fi;
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.DeletePagesByFolderPath", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@FolderPath", folderPath + "/%");
                        cmd.ExecuteNonQuery();
                    }

                    using (SqlCommand cmd = new SqlCommand("Lidocaine.GetFilePathByFolderPath", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@FolderPath", folderPath + "/%");
                        using (SqlDataReader rdr = cmd.ExecuteReader())
                        {
                            dt.Load(rdr);
                        }
                    }

                    foreach (DataRow dr in dt.Rows)
                    {
                        using (SqlCommand cmd = new SqlCommand("Lidocaine.DeleteFileByFilePath", conn))
                        {
                            cmd.CommandType = CommandType.StoredProcedure;
                            cmd.Parameters.AddWithValue("@FilePath", dr["FilePath"].ToString());
                            cmd.ExecuteNonQuery();
                        }

                        fi = new FileInfo(Environmental.StaticFilesDirectory + dr["FilePath"].ToString());
                        fi.Delete();
                    }

                    using (SqlCommand cmd = new SqlCommand("Lidocaine.DeleteFolder", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@FolderPath", folderPath);
                        cmd.ExecuteNonQuery();
                    }
                }

                output = "Successfully deleted folder \"/" + folderPath + "\" and contents.</li>";
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to add a page object to this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void AddPage(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                string path = string.IsNullOrEmpty(context.Request["path"]) ? string.Empty : context.Request["path"] + "/";
                string pageName = context.Request["name"];
                Regex myRegex = new Regex(@"^[\w]+$");
                if (myRegex.IsMatch(pageName))
                {
                    bool pageExists = true;
                    using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                    {
                        conn.Open();
                        using (SqlCommand cmd = new SqlCommand("Lidocaine.GetPageIDFromPagePath", conn))
                        {
                            cmd.CommandType = CommandType.StoredProcedure;
                            cmd.Parameters.AddWithValue("@PagePath", path + pageName + ".aspx");
                            using (SqlDataReader rdr = cmd.ExecuteReader())
                            {
                                if (!rdr.HasRows)
                                {
                                    pageExists = false;
                                }
                            }
                        }

                        if (!pageExists)
                        {
                            using (SqlCommand cmd = new SqlCommand("Lidocaine.InsertPage", conn))
                            {
                                cmd.CommandType = CommandType.StoredProcedure;
                                cmd.Parameters.AddWithValue("@PagePath", path + pageName + ".aspx");
                                cmd.ExecuteNonQuery();
                                output = "Successfully created page \"" + pageName + ".aspx\".";
                            }
                        }
                    }

                    if (pageExists)
                    {
                        output = "Creation failed: page already exists.";
                    }
                }
                else
                {
                    output = "Creation failed: please use only alphanumeric characters.";
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to add a folder object to this application.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void AddFolder(HttpContext context)
        {
            string output = string.Empty;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                string path = string.IsNullOrEmpty(context.Request["path"]) ? string.Empty : context.Request["path"] + "/";
                string folderName = context.Request["name"];
                Regex myRegex = new Regex(@"^[\w]+$");
                if (myRegex.IsMatch(folderName))
                {
                    bool folderExists = true;
                    using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                    {
                        conn.Open();
                        using (SqlCommand cmd = new SqlCommand("Lidocaine.GetFolderIDFromFolderPath", conn))
                        {
                            cmd.CommandType = CommandType.StoredProcedure;
                            cmd.Parameters.AddWithValue("@FolderPath", path + folderName);
                            using (SqlDataReader rdr = cmd.ExecuteReader())
                            {
                                if (!rdr.HasRows)
                                {
                                    folderExists = false;
                                }
                            }
                        }

                        if (!folderExists)
                        {
                            using (SqlCommand cmd = new SqlCommand("Lidocaine.InsertFolder", conn))
                            {
                                cmd.CommandType = CommandType.StoredProcedure;
                                cmd.Parameters.AddWithValue("@FolderPath", path + folderName);
                                cmd.ExecuteNonQuery();
                                output = "Successfully created folder \"" + folderName + "\".";
                            }
                        }
                    }

                    if (folderExists)
                    {
                        output = "Creation failed: folder already exists.";
                    }
                }
                else
                {
                    output = "Creation failed: please use only alphanumeric characters.";
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }

            context.Response.Write(output);
        }

        /// <summary>
        /// Handles the request to list the child files and directories of a virtual path.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void LoadExplorer(HttpContext context)
        {
            bool isAdmin = false;
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                isAdmin = true;
            }
            
            string path = context.Request["path"];
            string depth = context.Request["depth"];
            DataTable dt = new DataTable();
            dt.Locale = CultureInfo.InvariantCulture;
            using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
            {
                using (SqlCommand cmd = new SqlCommand("Lidocaine.LoadFiles", conn))
                {
                    if (!string.IsNullOrEmpty(path))
                    {
                        cmd.CommandText = "Lidocaine.LoadFiles2";
                        cmd.Parameters.AddWithValue("@Address", path);
                        cmd.Parameters.AddWithValue("@FolderCount", depth);
                    }

                    cmd.CommandType = CommandType.StoredProcedure;
                    conn.Open();
                    using (SqlDataReader rdr = cmd.ExecuteReader())
                    {
                        dt.Load(rdr);
                    }
                }
            }

            context.Response.Write("[{ \"N\": \"" + Environmental.Domain + "\", \"IsAdmin\": \"" + (isAdmin ? "1" : "0") + "\", \"Items\" : " + GetJSONString(dt) + "}]");
        }

        /// <summary>
        /// Handles the request to add permissions to a folder, page, or file object.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void AddPermissions(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                string strAllowType = context.Request["AllowType"];
                string strAllowID = context.Request["AllowID"];
                string strItemPath = context.Request["ItemPath"];
                string strItemID = string.Empty;
                string strItemType = string.Empty;
                
                if (strItemPath.EndsWith(".aspx", StringComparison.OrdinalIgnoreCase))
                {
                    strItemType = "0";
                    PageLayout page = new PageLayout(strItemPath);
                    strItemID = page.PageId.ToString();
                }
                else if (strItemPath.Contains("."))
                {
                    strItemType = "1";
                    Asset f = Asset.GetFileByVirtualPath(strItemPath);
                    strItemID = f.FileId.ToString(CultureInfo.InvariantCulture);
                }
                else
                {
                    strItemType = "2";
                    Folder folder = Folder.GetFolderByPath(strItemPath);
                    strItemID = folder.FolderId.ToString();
                }

                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.InsertPermission", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@PermissionItemType", strItemType);
                        cmd.Parameters.AddWithValue("@PermissionItemID", strItemID);
                        cmd.Parameters.AddWithValue("@PermissionAllowType", strAllowType);
                        cmd.Parameters.AddWithValue("@PermissionAllowID", strAllowID);
                        cmd.ExecuteNonQuery();
                    }
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }
        }

        /// <summary>
        /// Handles the request for the permissions on a folder object.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void GetFolderPermissions(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                DataTable dt = new DataTable();
                dt.Locale = CultureInfo.InvariantCulture;
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.GetFolderPermissions", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@FolderPath", context.Request["FolderPath"]);
                        using (SqlDataReader rdr = cmd.ExecuteReader())
                        {
                            dt.Load(rdr);
                        }
                    }
                }

                context.Response.Write(GetJSONString(dt));
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }
        }
        
        /// <summary>
        /// Handles the request for the permissions on a page object.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void GetPagePermissions(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                DataTable dt = new DataTable();
                dt.Locale = CultureInfo.InvariantCulture;
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.GetPagePermissions", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@PagePath", context.Request["PagePath"]);
                        using (SqlDataReader rdr = cmd.ExecuteReader())
                        {
                            dt.Load(rdr);
                        }
                    }
                }

                context.Response.Write(GetJSONString(dt));
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }
        }

        /// <summary>
        /// Handles the request for the permissions on a file object.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void GetFilePermissions(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                DataTable dt = new DataTable();
                dt.Locale = CultureInfo.InvariantCulture;
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.GetFilePermissions", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@VirtualPath", context.Request["VirtualPath"]);
                        using (SqlDataReader rdr = cmd.ExecuteReader())
                        {
                            dt.Load(rdr);
                        }
                    }
                }

                context.Response.Write(GetJSONString(dt));
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }
        }

        /// <summary>
        /// Handles the request to remove permissions to access an object from the web.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void RemovePermissions(HttpContext context)
        {
            IList<string> roles = Profile.Current.Roles;
            if (roles.Contains("Site Administrator") || roles.Contains("Content Manager"))
            {
                using (SqlConnection conn = new SqlConnection(Environmental.ConnectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand("Lidocaine.RemovePermissions", conn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@PermissionID", context.Request["PermissionID"]);
                        cmd.ExecuteNonQuery();
                    }
                }
            }
            else
            {
                throw new HttpException(401, Environmental.LogOnUrl.OriginalString + "?ReturnUrl=/cms/");
            }
        }

        /// <summary>
        /// Loads the description of the user control.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void LoadModuleDescription(HttpContext context)
        {
            int userControlId = 0;
            if (int.TryParse(context.Request["ID"], out userControlId))
            {
                UserControlAsset m = new UserControlAsset(userControlId);
                context.Response.Write(m.Description.Replace("\n", "<br />"));
            }
        }

        /// <summary>
        /// Loads user control names and IDs for selection.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void LoadModules(HttpContext context)
        {
            List<string> jsonMods = new List<string>();
            IList<UserControlAsset> mods = UserControlAsset.GetModules(UserControlArea.Main);
            for (int i = 0; i < mods.Count; i++)
            {
                jsonMods.Add(string.Format(CultureInfo.InvariantCulture, "{{\"ModuleID\" : \"{0}\",\"ModuleName\" : \"{1}\"}}", mods[i].ModuleId, mods[i].ModuleName));
            }

            context.Response.Write("[" + string.Join(", ", jsonMods.ToArray()) + "]");
        }

        /// <summary>
        /// Loads cascading style sheet scripts.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void LoadCSS(HttpContext context)
        {
            int cssId = 0;
            if (int.TryParse(context.Request.QueryString["ID"], out cssId))
            {
                Script script = new Script(cssId);
                if (script.ScriptType == ScriptType.Css)
                {
                    context.Response.Clear();
                    context.Response.ContentType = "text/css";
                    context.Response.Charset = Encoding.UTF8.WebName;
                    context.Response.Write(script.ScriptText);
                }
                else
                {
                    context.Response.Clear();
                    context.Response.ContentType = "text/css";
                    context.Response.Charset = Encoding.UTF8.WebName;
                    context.Response.Write("/* Empty File */");
                }
            }
            else
            {
                context.Response.Clear();
                context.Response.ContentType = "text/css";
                context.Response.Charset = Encoding.UTF8.WebName;
                context.Response.Write("/* Empty File */");
            }
        }

        /// <summary>
        /// Loads javascript scripts.
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void LoadJS(HttpContext context)
        {
            int scriptId = 0;
            if (int.TryParse(context.Request.QueryString["ID"], out scriptId))
            {
                Script script = new Script(scriptId);
                if (script.ScriptType == ScriptType.JS)
                {
                    context.Response.Clear();
                    context.Response.ContentType = "text/javascript";
                    context.Response.Charset = Encoding.UTF8.WebName;
                    context.Response.Write(script.ScriptText);
                }
                else
                {
                    context.Response.Clear();
                    context.Response.ContentType = "text/javascript";
                    context.Response.Charset = Encoding.UTF8.WebName;
                    context.Response.Write("/* Empty File */");
                }
            }
            else
            {
                context.Response.Clear();
                context.Response.ContentType = "text/javascript";
                context.Response.Charset = Encoding.UTF8.WebName;
                context.Response.Write("/* Empty File */");
            }
        }

        /// <summary>
        /// Uploads static files from Uploadify (flash multi-upload jQuery extension)
        /// </summary>
        /// <param name="context">The current HTTP context object.</param>
        private void Upload(HttpContext context)
        {
            bool goodToUpload = true;
            int userID = 0;
            HttpPostedFile file = context.Request.Files["Filedata"];
            string filepath = context.Request["strFilepath"];
            string cookie = context.Request["strCookie"];
            bool unzip = context.Request["unzip"] == "yes" ? true : false;
            HttpCookie encoded = new HttpCookie("Lidocaine", cookie);
            HttpCookie decoded = HttpSecureCookie.Decode(encoded);
            userID = Convert.ToInt32(decoded.Values["ID"], CultureInfo.InvariantCulture);
            Profile currentUser = new Profile(userID);
            IList<string> roles = currentUser.Roles;
            if (!roles.Contains("Site Administrator") && !roles.Contains("Content Manager") && !roles.Contains("Content Provider"))
            {
                goodToUpload = false;
                context.Response.Write("Upload Failed on " + file.FileName + ":  Upload Permission Denied.");
            }

            if (goodToUpload && unzip && file.FileName.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
            {
                DirectoryInfo di = new DirectoryInfo(Environmental.StaticFilesDirectory + @"\temp");
                if (!di.Exists)
                {
                    di.Create();
                }

                try
                {
                    int i = 0;
                    FileInfo fi = new FileInfo(Environmental.StaticFilesDirectory + @"\temp\" + i + file.FileName);
                    while (fi.Exists)
                    {
                        i++;
                        fi = new FileInfo(Environmental.StaticFilesDirectory + @"\temp\" + i + file.FileName);
                    }

                    file.SaveAs(Environmental.StaticFilesDirectory + @"\temp\" + i + file.FileName);
                    ZipFile z = new ZipFile(Environmental.StaticFilesDirectory + @"\temp\" + i + file.FileName);
                    int j = 0;
                    di = new DirectoryInfo(Environmental.StaticFilesDirectory + @"\temp\" + j);
                    while (di.Exists)
                    {
                        j++;
                        di = new DirectoryInfo(Environmental.StaticFilesDirectory + @"\temp\" + j);
                    }
                    
                    z.ExtractAll(Environmental.StaticFilesDirectory + @"\temp\" + j);
                    context.Response.Write(this.RecursiveFileImport(di, filepath));
                    z.Dispose();
                    di.Delete(true);
                    fi.Delete();
                }
                catch (Exception ex)
                {
                    context.Response.Write("Upload Failed on " + file.FileName + ": " + ex.Message.ToString());
                }
            }
            else if (goodToUpload)
            {
                Regex myRegex = new Regex(@"^[\w.]+$");
                if (!myRegex.IsMatch(file.FileName))
                {
                    goodToUpload = false;
                    context.Response.Write("Upload Failed on " + file.FileName + ":  Please use only alphanumeric characters, \"_\" and \".\".");
                }

                FileType filetype = FileType.GetFileTypeByExtension(file.FileName.Substring(file.FileName.LastIndexOf(".", StringComparison.Ordinal) + 1));
                if (filetype == null)
                {
                    goodToUpload = false;
                    context.Response.Write("Upload Failed on " + file.FileName + ":  This file type is not hosted.");
                }

                if (!string.IsNullOrEmpty(filepath))
                {
                    filepath += "/";
                }

                Asset f = Asset.GetFileByVirtualPath(filepath + file.FileName);
                if (f != null)
                {
                    goodToUpload = false;
                    context.Response.Write("Upload Failed on " + file.FileName + ":  Another file with the same name already exists.");
                }

                if (goodToUpload)
                {
                    f = new Asset();
                    f.VirtualPath = filepath + file.FileName;
                    f.FileType = filetype;
                    f.SaveAs();

                    try
                    {
                        file.SaveAs(Environmental.StaticFilesDirectory + @"\" + f.FileId + "." + f.FileType.Extension);
                        context.Response.Write("Upload Successful on " + file.FileName + ".");
                    }
                    catch (Exception ex)
                    {
                        f.Delete();
                        context.Response.Write("Upload Failed on " + file.FileName + ": " + ex.Message.ToString());
                    }
                }
            }
        }

        /// <summary>
        /// Recursively enters zipped document contents into the database.
        /// </summary>
        /// <param name="di">The current directory to import.</param>
        /// <param name="filepath">The current location for imports to be placed.</param>
        /// <returns>A string representing the status of the file import.</returns>
        private string RecursiveFileImport(DirectoryInfo di, string filepath)
        {
            StringBuilder output = new StringBuilder();
            if (!string.IsNullOrEmpty(filepath))
            {
                filepath += "/";
            }

            // import directories
            Folder folder;
            DirectoryInfo[] childDirectories = di.GetDirectories();
            for (int i = 0; i < childDirectories.Length; i++)
            {
                folder = Folder.GetFolderByPath(filepath + childDirectories[i].Name);
                if (folder == null)
                {
                    folder = new Folder();
                    folder.FolderPath = filepath + childDirectories[i].Name;
                    folder.SaveAs();
                    output.Append(this.RecursiveFileImport(childDirectories[i], folder.FolderPath) + "<br />");
                }
                else
                {
                    output.Append("Upload Failed on " + folder.FolderPath + "/" + childDirectories[i].Name + ": folder already exists.<br />");
                }
            }

            // import files
            bool goodToUpload = true;
            FileInfo[] childFiles = di.GetFiles();
            for (int i = 0; i < childFiles.Length; i++)
            {
                Regex myRegex = new Regex(@"^[\w.]+$");
                if (!myRegex.IsMatch(childFiles[i].Name))
                {
                    goodToUpload = false;
                    output.Append("Upload Failed on " + childFiles[i].Name + ":  Please use only alphanumeric characters, \"_\" and \".\".<br />");
                }

                FileType filetype = FileType.GetFileTypeByExtension(childFiles[i].Extension.TrimStart('.'));
                if (filetype == null)
                {
                    goodToUpload = false;
                    output.Append("Upload Failed on " + childFiles[i].Name + ":  This file type is not hosted.<br />");
                }

                Asset f = Asset.GetFileByVirtualPath(filepath + childFiles[i].Name);
                if (f != null)
                {
                    goodToUpload = false;
                    output.Append("Upload Failed on " + childFiles[i].Name + ":  Another file with the same name already exists.<br />");
                }

                if (goodToUpload)
                {
                    f = new Asset();
                    f.VirtualPath = filepath + childFiles[i].Name;
                    f.FileType = filetype;
                    f.SaveAs();

                    try
                    {
                        childFiles[i].CopyTo(Environmental.StaticFilesDirectory + @"\" + f.FileId + "." + f.FileType.Extension);
                        output.Append("Upload Successful on " + childFiles[i].Name + ".<br />");
                    }
                    catch (Exception ex)
                    {
                        f.Delete();
                        output.Append("Upload Failed on " + childFiles[i].Name + ": " + ex.Message.ToString() + "<br />");
                    }
                }
            }

            return output.ToString();
        }

        /// <summary>
        /// Loads the dictionary mapping input strings to their associated method.
        /// </summary>
        /// <returns>A dictionary of strings mapped to methods.</returns>
        private Dictionary<string, Action<HttpContext>> GetHandlers()
        {
            Dictionary<string, Action<HttpContext>> d = new Dictionary<string, Action<HttpContext>>
            {
                { "DeleteFileType", this.DeleteFileType },
                { "AddFileType", this.AddFileType },
                { "UpdateFileType", this.UpdateFileType },
                { "LoadFileTypes", this.LoadFileTypes },
                { "UpdatePageSettingsTitle", this.UpdatePageSettingsTitle },
                { "UpdatePageSettingsHeader", this.UpdatePageSettingsHeader },
                { "UpdatePageSettingsFooter", this.UpdatePageSettingsFooter },
                { "UpdatePageSettingsCSS", this.UpdatePageSettingsCSS },
                { "UpdatePageSettingsJS", this.UpdatePageSettingsJS },
                { "UpdatePageSettingsTopNavOrder", this.UpdatePageSettingsTopNavOrder },
                { "UpdatePageSettingsLeftNavOrder", this.UpdatePageSettingsLeftNavOrder },
                { "UpdatePageSettingsTopNavRemove", this.UpdatePageSettingsTopNavRemove },
                { "UpdatePageSettingsLeftNavRemove", this.UpdatePageSettingsLeftNavRemove },
                { "UpdatePageSettingsTopNavAdd", this.UpdatePageSettingsTopNavAdd },
                { "UpdatePageSettingsLeftNavAdd", this.UpdatePageSettingsLeftNavAdd },
                { "UpdatePageSettingsRightOrder", this.UpdatePageSettingsRightOrder },
                { "UpdatePageSettingsMainOrder", this.UpdatePageSettingsMainOrder },
                { "UpdatePageSettingsRightRemove", this.UpdatePageSettingsRightRemove },
                { "UpdatePageSettingsMainRemove", this.UpdatePageSettingsMainRemove },
                { "UpdatePageSettingsRightAdd", this.UpdatePageSettingsRightAdd },
                { "UpdatePageSettingsMainAdd", this.UpdatePageSettingsMainAdd },
                { "UpdatePageSettingsContentVersion", this.UpdatePageSettingsContentVersion },
                { "EditPageSettings", this.EditPageSettings },
                { "AddTopNavItem", this.AddTopNavItem },
                { "AddLeftNavItem", this.AddLeftNavItem },
                { "DeleteTopNavItem", this.DeleteTopNavItem },
                { "DeleteLeftNavItem", this.DeleteLeftNavItem },
                { "UpdateTopNavItemOrder", this.UpdateTopNavItemOrder },
                { "UpdateLeftNavItemOrder", this.UpdateLeftNavItemOrder },
                { "EditTopNav", this.EditTopNav },
                { "EditLeftNav", this.EditLeftNav },
                { "SaveAndPublishPage", this.SaveAndPublishPage },
                { "SavePage", this.SavePage },
                { "EditPage", this.EditPage },
                { "AddLeftNav", this.AddLeftNav },
                { "AddTopNav", this.AddTopNav },
                { "LoadLeftNav", this.LoadLeftNav },
                { "LoadTopNav", this.LoadTopNav },
                { "AddRModule", this.AddRModule },
                { "DeleteRModule", this.DeleteRModule },
                { "LoadRModules", this.LoadRModules },
                { "AddMModule", this.AddMModule },
                { "DeleteMModule", this.DeleteMModule },
                { "LoadMModules", this.LoadMModules },
                { "UpdateJs", this.UpdateJs },
                { "EditJs", this.EditJs },
                { "AddJs", this.AddJs },
                { "DeleteJs", this.DeleteScript },
                { "RenameJs", this.RenameJs },
                { "LoadJs", this.LoadJs },
                { "UpdateCss", this.UpdateCss },
                { "EditCss", this.EditCss },
                { "AddCss", this.AddCss },
                { "DeleteCss", this.DeleteScript },
                { "RenameCss", this.RenameCss },
                { "LoadCss", this.LoadCss },
                { "UpdateHeader", this.UpdateHeader },
                { "EditHeader", this.EditHeader },
                { "AddHeader", this.AddHeader },
                { "RenameHeader", this.RenameHeader },
                { "LoadHeaders", this.LoadHeaders },
                { "UpdateFooter", this.UpdateFooter },
                { "EditFooter", this.EditFooter },
                { "AddFooter", this.AddFooter },
                { "DeleteTemplate", this.DeleteTemplate },
                { "RenameFooter", this.RenameFooter },
                { "LoadFooters", this.LoadFooters },
                { "LoadUsers", this.LoadUsers },
                { "DeleteUser", this.DeleteUser },
                { "UpdateUser", this.UpdateUser },
                { "AddUser", this.AddUser },
                { "LoadGroups", this.LoadGroups },
                { "RenameFile", this.RenameFile },
                { "RenamePage", this.RenamePage },
                { "RenameFolder", this.RenameFolder },
                { "DeleteFile", this.DeleteFile },
                { "DeletePage", this.DeletePage },
                { "DeleteFolder", this.DeleteFolder },
                { "AddPage", this.AddPage },
                { "AddFolder", this.AddFolder },
                { "LoadExplorer", this.LoadExplorer },
                { "AddPermissions", this.AddPermissions },
                { "GetFolderPermissions", this.GetFolderPermissions },
                { "GetPagePermissions", this.GetPagePermissions },
                { "GetFilePermissions", this.GetFilePermissions },
                { "RemovePermissions", this.RemovePermissions },
                { "LoadCSS", this.LoadCSS },
                { "LoadJS", this.LoadJS },
                { "LoadModules", this.LoadModules },
                { "LoadModuleDescription", this.LoadModuleDescription },
                { "Upload", this.Upload }
            };

            return d;
        }
        #endregion
    }
}